Materialize per-layer artifacts with explicit whiteout handling - #456
Materialize per-layer artifacts with explicit whiteout handling#456chruffins wants to merge 2 commits into
Conversation
2ea330e to
57b4c9c
Compare
57b4c9c to
d2068dc
Compare
a08da7b to
6e93aa4
Compare
4a6cbdf to
85d7ec5
Compare
85d7ec5 to
70c6422
Compare
de55693 to
e8b5a05
Compare
e8b5a05 to
0374d70
Compare
93d7a10 to
335b70d
Compare
3ad12a5 to
eb2b97b
Compare
68bf31c to
d883208
Compare
04e6138 to
36ccb28
Compare
36ccb28 to
06f8b54
Compare
06f8b54 to
041b07a
Compare
041b07a to
aa3a5ea
Compare
fde98d0 to
a0d2aba
Compare
14cee93 to
4c270b0
Compare
4c270b0 to
fcd3558
Compare
5248289 to
328ebcf
Compare
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d4ed105. Configure here.
cb96be2 to
7b8f9ef
Compare
59eb8fb to
f18a718
Compare
-->
✱ stlc build✅ go code · compare
✅ python code · compare
✅ typescript code · compare
Diagnostics: 💡 0 new / 5 total note
Build metadata
This comment is auto-generated by stlc and is kept up to date as you push. |
Adds a content-addressed layer store under images/layers/<blob digest>/. A layer is unpacked from the shared OCI cache with umoci, converted to the default disk format, and installed as layer.<format> plus an artifact record, atomically. One layer shared across images materializes once, and callers racing on the same layer share a single build through singleflight, bounded by a manager-level semaphore and a one hour deadline so a hung read cannot wedge the key forever. Whiteouts use the representation overlayfs stacking requires: .wh.<name> becomes a 0:0 character device and .wh..wh..opq becomes a trusted.overlay.opaque xattr. A startup probe checks the host can create both; rootless Linux, macOS and filesystems without trusted xattrs skip per-layer artifacts and compose OCI layers into one rootfs with the userspace whiteout path, which keeps image contents identical. Extraction confines every entry to the destination, verifies the compressed blob digest and the diff ID, and caps the decompressed stream. Layer artifact bytes are counted with the OCI cache in TotalOCICacheBytes.
GetBreakdown swallowed per-subsystem errors and reported a zero for the category that failed, which reads as free disk. It now returns the error.
1e65916 to
6157365
Compare

tldr
Content-addressed per-layer artifact store at
images/layers/<layer-blob-digest>/. Pulls and composition (next PR in the stack) share it. Native layer artifacts are Linux-root-only; rootless Linux and macOS use the merged-rootfs path instead, with no image-content change.what this adds
materializeLayerArtifact) — unpacks a layer blob from the existing shared OCI cache with umoci, converts to erofs, installslayer.erofs+ anartifact.jsonrecord atomically. Same layer shared across images materializes once; concurrent callers share one build (singleflight), with a manager-level concurrency bound..wh.<name>becomes a0:0char device and.wh..wh..opqbecomes atrusted.overlay.opaquexattr. This is the standard representation required by later overlayfs stacking; it is not attempted where the host cannot create it.mknodand trusted overlay xattr support on the layer-store filesystem. Rootless Linux, macOS, and unsupported filesystems skip per-layer artifact materialization and compose OCI layers into one rootfs withDirRootfs, which applies whiteouts in userspace. This preserves image semantics while giving up per-layer sharing on those hosts.TotalOCICacheBytes(conservative: blob + artifact of the same layer may transiently coexist). Active builds keep totals uncached, and disk-usage scans retry if invalidated while a scan is in progress.review status: done
Two independent review passes (correctness + code-quality). Findings and how they are handled:
composeOnDiskFormat+whiteoutPrefixmoved to tests,multiCloserdeleted, blob path viapaths.OCICacheBlobVerified empirically on a dev host:
mkfs.erofs1.8.10 andmkfs.ext4both preserve whiteout char devices and opaque xattrs throughExportRootfson the supported Linux-root path. Depends on host erofs-utils version; check it in the pull-integration PR.reviewer focus (3 things)
layerBuildTimeout= 1h is a judgment call — flag if hypeman has a convention for bounding background work#458wires the store into production. It skips layer materialization on unsupported hosts and retains blob-based merged-rootfs composition as the fallback.validation
Full
lib/images+lib/pathsgreen on a rootless host; capability-gated whiteout/device tests pass or skip based on an actualmknod+ trusted-xattr probe. Tests cover: materialize/reuse/rebuild, corrupt-record recovery, same-size artifact corruption, invalid digest rejection (sha256:..,sha256:a/b), whiteout/opaque output and cross-layer semantics, symlink confinement and replacement, hardlinks, cancellation, zstd + docker media types, concurrent singleflight (8 callers, one build), trailing-padding diff IDs. The exported erofs whiteout round trip moves to the composition PR, which is where the host erofs-utils version gets checked.CI note: the
testworkflow is flaky on this branch — failures are unrelated integration tests (TestEgressProxyRewritesHTTPSHeaderstimeout, docker/network tests needingnginx:alpine), failing before the latest commits too. Layer-artifact tests pass consistently.next step
Review the focus items above, then approve. PR
#458is the production caller and lifecycle follow-up.Note
Medium Risk
New layer unpack and filesystem materialization touches tar extraction and external mkfs tools; incorrect whiteout or path handling could affect future image composition, though pull behavior is unchanged until wired in.
Overview
Introduces a content-addressed per-layer artifact store under
images/layers/<blob-digest>/, keyed by compressed layer digest plus format (erofs/ext4).materializeLayerArtifactreads blobs from the existing OCI cache, unpacks with umoci into a temp dir, converts to the default disk format, and installslayer.*plus anartifact.*.jsonrecord atomically; duplicate work is deduped with singleflight and valid on-disk records are reused.Whiteouts are modeled explicitly: artifact extraction uses umoci
OverlayfsRootfs(character-device whiteouts and opaque xattrs) so stacked layers can be mounted later; compose-oriented unpacking usesDirRootfs. Layer unpack supports gzip/zstd, verifies diff IDs, caps unpacked size at 100 GiB, and honors context cancellation via acontextReaderandCommandContextformkfs.erofs.Disk accounting now walks
layer.*files (skipping.unpack-*temps) and folds that intoTotalOCICacheBytes/ resource admission alongside OCI blobs. New path helpers live inlib/paths. The materialization API is implemented and tested; production wiring is in follow-up PR#458, which skips it on unsupported hosts.Reviewed by Cursor Bugbot for commit d4ed105. Configure here.